/**
  *
  */

#include "game.h"
#include <QTime>
#include "metaballs.h"

// for readability, the screen and texture sizes are hard-coded
const float SCREEN_WIDTH=640.0f;
const float SCREEN_HEIGHT=360.0f;

const VGfloat backgroundColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };

VGPath path;
VGPaint paint;

// temp buffer for transformed path coordinates

VGubyte moveTo=VG_MOVE_TO_ABS;
VGubyte lineTo=VG_LINE_TO_ABS;
VGubyte closePath=VG_CLOSE_PATH;

/** walltime */
float t;


#define BALL_COUNT 16

Ball balls[]=
{
    Ball(QVector2D(350, 100), 4),
    Ball(QVector2D(20, 200), 2),
    Ball(QVector2D(280, 140), 2),
    Ball(QVector2D(400, 440), 3),

    Ball(QVector2D(150, 100), 3),
    Ball(QVector2D(320, 300), 3),
    Ball(QVector2D(510, 140), 3),
    Ball(QVector2D(200, 240), 3),

    Ball(QVector2D(150, 100), 3),
    Ball(QVector2D(320, 300), 3),
    Ball(QVector2D(510, 140), 3),
    Ball(QVector2D(200, 240), 3),

    Ball(QVector2D(150, 100), 3),
    Ball(QVector2D(320, 300), 3),
    Ball(QVector2D(510, 140), 3),
    Ball(QVector2D(200, 240), 3),
};

MetaballSystem mbs(BALL_COUNT, balls, 2.0, 4*0.0015);

VGPath blobs[BALL_COUNT];

void game_init()
{
}

void game_destroy()
{
}


void game_prepare()
{
    vgSeti(VG_FILL_RULE, VG_NON_ZERO);

    paint = vgCreatePaint();

    vgSetParameteri(paint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
    vgSetColor(paint, 0xff00ffff);

    path=vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 0, 0, VG_PATH_CAPABILITY_ALL);
    vguRect(path, 0, 0, 4, 4);

    for(int i=0;i<mbs.ballCount;i++)
    {
        blobs[i]=vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 0, 0, VG_PATH_CAPABILITY_ALL);
    }

}

void game_release()
{
    vgDestroyPath(path);
    vgDestroyPaint(paint);
    for(int i=0;i<mbs.ballCount;i++)
    {
        vgDestroyPath(blobs[i]);
    }
}

int frames=0;

void game_update(float walltime)
{
    t=walltime;
}

void debug_point(float x, float y, int color)
{
    vgLoadIdentity();
    vgTranslate(x, y);
    vgSetColor(paint, color);
    vgSetPaint(paint, VG_FILL_PATH | VG_STROKE_PATH);
    vgDrawPath(path, VG_FILL_PATH | VG_STROKE_PATH);
    vgLoadIdentity();
}



void draw_balls()
{
    float step = 10;

    /*
    # First, track the border for all balls and store
    # it to pos0 and edgePos. The latter will move along the border,
    # pos0 stays at the initial coordinates.
     */
    for(int i=0;i<mbs.ballCount;i++)
    {
        Ball &b = mbs.balls[i];
        b.pos = QVector2D(sin(t*.2+i*7.1)*200+320,cos(i*4.1+t*.3)*150+180);
        QVector2D p=b.pos;
        b.pos0 = mbs.trackTheBorder(b.pos+QVector2D(0,1));
        b.edgePos = b.pos0;
        b.tracking = true;
        b.sharedBall=-1;
        b.verticeCount=0;

        vgClearPath(blobs[i], VG_PATH_CAPABILITY_APPEND_TO);

        p=b.pos0;
        float xy[2]={p.x(), SCREEN_HEIGHT-p.y()};
#if 0
        debug_point(xy[0], xy[1], 0xff0000ff);
#endif
//        vgAppendPathData(blobs[i], 1, &moveTo, xy);

        b.commands[b.verticeCount]=VG_MOVE_TO_ABS;
        b.vertices[b.verticeCount*2]=xy[0];
        b.vertices[b.verticeCount*2+1]=xy[1];

        b.verticeCount++;

    }

//
    for(int i=0;i<mbs.ballCount;i++)
    {
        /*if(i!=1 & i!=6)
        {
            continue;
        }*/
        for(int c=0;c<100;c++)
        {
            Ball &ball = mbs.balls[i];
            if(!ball.tracking)
            {
                continue;
            }

            //# walk along the tangent, using chosen differential method
            ball.edgePos = mbs.rungeKutta2Tangent(ball.edgePos, step);

            //# correction step towards the border
            mbs.stepOnceTowardsBorder(ball.edgePos);

            //# check if we've gone a full circle or hit some other
            //# edge tracker

            int otherball=-1;
            for(int j=0;j<mbs.ballCount;j++)
            {
                Ball &ob = mbs.balls[j];
                if((i!=j || c>3) && (ob.pos0-ball.edgePos).lengthSquared()<step*step)
                {
                    ball.tracking=false;
                    otherball=j;
                }
            }

            QVector2D p=ball.edgePos;
            float xy[2]={p.x(), SCREEN_HEIGHT-p.y()};
#if 0
            int color=-1;


            if(c==0)
                color = 0x00fff020+c*16;
            else if(otherball==-1)
                color = 0xff008020+c*16;


            debug_point(xy[0], xy[1], color);

#endif

            //vgAppendPathData(blobs[i], 1, &lineTo, xy);

            ball.commands[ball.verticeCount]=VG_LINE_TO_ABS;
            ball.vertices[ball.verticeCount*2]=xy[0];
            ball.vertices[ball.verticeCount*2+1]=xy[1];
            ball.verticeCount++;

            if(otherball!=-1)
            {
                //qDebug("otherball %d %d %d", i, otherball, c);
                QVector2D p=balls[otherball].pos0;
                float xy[2]={p.x(), SCREEN_HEIGHT-p.y()};
                //vgAppendPathData(blobs[i], 1, &lineTo, xy);
                //ball.verticeCounr++;

                ball.commands[ball.verticeCount]=VG_LINE_TO_ABS;
                ball.vertices[ball.verticeCount*2]=xy[0];
                ball.vertices[ball.verticeCount*2+1]=xy[1];
                ball.verticeCount++;

                //    vgAppendPathData(blobs[i], 1, &closePath, xy);
            }
        }

        vgLoadIdentity();
        vgAppendPathData(blobs[i], mbs.balls[i].verticeCount, mbs.balls[i].commands, mbs.balls[i].vertices);

        //qDebug("vertices %d", mbs.balls[i].verticeCount);
        vgSetColor(paint, 0xffffff7f);
        vgSetPaint(paint, VG_FILL_PATH | VG_STROKE_PATH);
        vgDrawPath(blobs[i], 0*VG_FILL_PATH | VG_STROKE_PATH);

    }
/*
    //qDebug("draw");
    vgLoadIdentity();
    for(int i=0;i<mbs.ballCount;i++)
    {
        vgAppendPathData(blobs[i], mbs.balls[i].verticeCount, mbs.balls[i].commands, mbs.balls[i].vertices);

        //qDebug("vertices %d", mbs.balls[i].verticeCount);
        vgSetColor(paint, 0xffffff7f);
        vgSetPaint(paint, VG_FILL_PATH | VG_STROKE_PATH);
        vgDrawPath(blobs[i], 0*VG_FILL_PATH | VG_STROKE_PATH);

    }
*/
}

void game_render()
{
    // clear background
    vgSetfv(VG_CLEAR_COLOR, 4, backgroundColor);
    vgClear(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);

    // center to screen
    vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
    //vgTranslate(SCREEN_WIDTH/2, SCREEN_HEIGHT/2);

    // update VG path coordinates
    // vgModifyPathCoords(sides[c], 0, 4, pathVertices);

    frames++;

    vgSetColor(paint, 0xffff00ff);
    for(int i=0;i<mbs.ballCount;i++)
    {
        //qDebug("ball %d shared with %d", i, mbs.balls[i].sharedBall);

        vgLoadIdentity();
        QVector2D p=mbs.balls[i].pos;
        vgTranslate(p.x(), SCREEN_HEIGHT-p.y());

        vgSetPaint(paint, VG_FILL_PATH);
        vgDrawPath(path, VG_FILL_PATH);
    }

    vgSetPaint(paint, VG_STROKE_PATH);
    vgSeti(VG_STROKE_CAP_STYLE, VG_CAP_BUTT);

    vgSetf(VG_STROKE_LINE_WIDTH, 8);

    draw_balls();


}

void game_event(int type, float x, float y, float z)
{
    balls[0].pos = QVector2D(x,y);
}
